#include <tsapicvi.h>
#include "Swift_DUTreader.h"
#include <utility.h>
#include "stdtst.h"
#include "tsutil.h"

int CVICALLBACK DutReaderThread( void *functionData );
int WaitFixtureClosed( const int iDutPosition );

BOOL g_bBay1Scanned = FALSE;
BOOL g_bBay2Scanned = FALSE;
BOOL g_bBay1Testing = FALSE;
BOOL g_bBay2Testing = FALSE;
BOOL g_bReaderActive = FALSE;
VBOOL g_bContinueTesting = TRUE;

int g_iDutReaderThread = 0;

char g_szDut1SerialNumber[12] = {'\0'};
char g_szDut2SerialNumber[12] = {'\0'};
char g_szDut1ProductCode[17] = {'\0'};
char g_szDut2ProductCode[17] = {'\0'};

CAObjHandle g_hDutReader = 0;
VARIANT g_vaThisContext;  

int CVICALLBACK E_StartButton (int panel, int control, int event,
                               void *callbackData, int eventData1,
                               int eventData2);

void __declspec(dllexport) TX_TEST ClearDutReaderFlags( tTestData* testData, tTestError* testError )
{
	g_bBay1Scanned = FALSE;
	g_bBay2Scanned = FALSE;
	g_bBay1Testing = FALSE;
	g_bBay2Testing = FALSE;
	g_bReaderActive = FALSE;
	g_bContinueTesting = TRUE;
	strcpy( g_szDut1SerialNumber, "\0" );
	strcpy( g_szDut2SerialNumber, "\0" );
	strcpy( g_szDut1ProductCode, "\0" );
	strcpy( g_szDut2ProductCode, "\0" );
}

void __declspec(dllexport) TX_TEST StartDutReaderThread( tTestData* testData, tTestError* testError )
{
	void* pVoid = 0;
	
	CA_SetSupportForMultithreading( testData->seqContextCVI, 1 );
	CA_VariantSetObjHandle( &g_vaThisContext, testData->seqContextCVI, CAVT_UNKNOWN ); 

	CmtScheduleThreadPoolFunction( DEFAULT_THREAD_POOL_HANDLE, DutReaderThread, pVoid, &g_iDutReaderThread );
	
	Delay( 2.0 );
}

void __declspec(dllexport) TX_TEST StopDutReaderThread( tTestData* testData, tTestError* testError )
{

	if( g_iDutReaderThread != 0 )
	{
		CmtWaitForThreadPoolFunctionCompletion( DEFAULT_THREAD_POOL_HANDLE,
											g_iDutReaderThread, 0 );
	}
	
	if( g_hDutReader != 0 )
	{
		SWIFTDUTREADERLib_IDUTReaderTerminate( g_hDutReader, NULL );
		g_hDutReader = 0;
	}

	CA_VariantClear( &g_vaThisContext );

	if( g_iDutReaderThread != 0 )
	{
		CmtReleaseThreadPoolFunctionID( DEFAULT_THREAD_POOL_HANDLE, g_iDutReaderThread );
		g_iDutReaderThread = 0;
	}
}

int CVICALLBACK DutReaderThread( void *functionData )
{
	long lSuccess = 0;
	char* pszSerial = 0;
	char* pszPCode = 0;
	char szSlot[21] = {'\0'};
	int iSlot = 0;
	int iError = 0;
	BOOL bRepeat = FALSE;
	ERRORINFO errorInfo;
	CAObjHandle hSeqContextCVI = 0;

	if( g_hDutReader == 0 )
	{
		SWIFTDUTREADERLib_NewIDUTReader( NULL, 1, LOCALE_NEUTRAL, 0, &g_hDutReader );
		SWIFTDUTREADERLib_IDUTReaderInitialize( g_hDutReader, NULL, &lSuccess );
	}
	
	CA_VariantGetObjHandle( &g_vaThisContext, &hSeqContextCVI );
	CA_VariantSetObjHandle( &g_vaThisContext, hSeqContextCVI, CAVT_UNKNOWN ); 

	for( ;; )
	{
		if( g_hDutReader != 0 )
		{
			if( g_bReaderActive == FALSE )
			{
				g_bReaderActive = TRUE;
				
				if( g_bBay1Scanned == FALSE || g_bBay2Scanned == FALSE )
				{
					do
					{
						bRepeat = FALSE;
						
						iError = SWIFTDUTREADERLib_IDUTReaderInvokeDUTReader( g_hDutReader, NULL, g_vaThisContext, &lSuccess );
	
						iError = TS_PropertyGetValBoolean( hSeqContextCVI, &errorInfo, "StationGlobals.NSN.DUT.ContinueTesting", 0, &g_bContinueTesting );
						
						if( g_bContinueTesting == FALSE )
						{
							break;
						}
						else
						{
						}

						PromptPopup( "Slot ID", "Please scan Slot ID", szSlot, 20 );

						iSlot = atoi( szSlot );
						
						if( iSlot == 1 && g_bBay1Scanned == TRUE )
						{
							bRepeat = TRUE;
							MessagePopup( "Error", "Slot 1 is already scanned" );
						}
						else if( iSlot == 2 && g_bBay2Scanned == TRUE )
						{
							bRepeat = TRUE;
							MessagePopup( "Error", "Slot 2 is already scanned" );
						}
						else if( iSlot > 2 || iSlot < 1 )
						{
							bRepeat = TRUE;
							MessagePopup( "Error", "Invalid slot ID.\nMust be either 1 or 2." );
						}
					}
					while( bRepeat );
					
					if( g_bContinueTesting == FALSE )
					{
						break;
					}

					//Retrieve and store serial and pcode to be swapped back after non active bay has been read
					if( iSlot == 1 )
					{
						TS_PropertyGetValString( hSeqContextCVI, &errorInfo, "StationGlobals.NSN.DUT.SerialNumber", 0, &pszSerial );

						strcpy( g_szDut1SerialNumber, pszSerial );
						if( pszSerial != 0 )
						{
							CA_FreeMemory( pszSerial );
							pszSerial = 0;
						}
						TS_PropertyGetValString( hSeqContextCVI, &errorInfo, "StationGlobals.NSN.DUT.ProductCode", 0, &pszPCode );
						strcpy( g_szDut1ProductCode, pszPCode );
						if( pszPCode != 0 )
						{
							CA_FreeMemory( pszPCode );
							pszPCode = 0;
						}
					
						g_bBay1Scanned = TRUE;

					}
					else if( iSlot == 2 )
					{
						iError = TS_PropertyGetValString( hSeqContextCVI, &errorInfo, "StationGlobals.NSN.DUT.SerialNumber", 0, &pszSerial );
						strcpy( g_szDut2SerialNumber, pszSerial );
						if( pszSerial != 0 )
						{
							CA_FreeMemory( pszSerial );
							pszSerial = 0;
						}
						TS_PropertyGetValString( hSeqContextCVI, &errorInfo, "StationGlobals.NSN.DUT.ProductCode", 0, &pszPCode );
						strcpy( g_szDut2ProductCode, pszPCode );
						if( pszPCode != 0 )
						{
							CA_FreeMemory( pszPCode );
							pszPCode = 0;
						}
					
						g_bBay2Scanned = TRUE;
					}
		 		}
		 	} // if !g_bReaderActive
		 	
		 	g_bReaderActive = FALSE;
		}
		
		Delay( 2.0 );
	} // for( ;; )	
	
	if( hSeqContextCVI != 0 )
	{
		CA_DiscardObjHandle( hSeqContextCVI );
		hSeqContextCVI = 0;
	}

	return 0;
}

void __declspec(dllexport) TX_TEST WaitForTurn( tTestData* testData, tTestError* testError )
{
	BOOL bRepeat 		= FALSE;
	BOOL bLineStatus 	= FALSE;
	ERRORINFO errorInfo;
	ErrMsg errMsg 		= {'\0'};
	int error 			= 0;

	if( g_iDutReaderThread != 0 )
	{
		do
		{
			bRepeat = FALSE;
		
			if( g_bBay1Scanned == FALSE && g_bBay2Scanned == FALSE )
			{
				bRepeat = TRUE;
				if( g_bContinueTesting == FALSE )
				{
					bRepeat = FALSE;
				}
			}
			else
			{
				if( g_bBay1Scanned == TRUE && g_bBay2Testing == FALSE )
				{
					g_bBay1Testing = TRUE;
					bRepeat = FALSE;
					tsErrChk( TS_PropertySetValString( testData->seqContextCVI, &errorInfo, "Parameters.DUT.SerialNumber", 0, g_szDut1SerialNumber ) );
					tsErrChk( TS_PropertySetValString( testData->seqContextCVI, &errorInfo, "Parameters.DUT.ProductCode", 0, g_szDut1ProductCode ) );
					tsErrChk( TS_PropertySetValNumber( testData->seqContextCVI, &errorInfo, "Parameters.DUT.TestSocketIndex", 0, 0 ) );
					SSU_GetFixtureClosedStatus( 1, &bLineStatus );
					
					if( bLineStatus == FALSE )
						WaitFixtureClosed( 1 );

					SSU_SwitchLed( 1, TRUE );
					SSU_EnablePa( 1, FALSE );
				}
				else if( g_bBay2Scanned == TRUE && g_bBay1Testing == FALSE )
				{
					g_bBay2Testing = TRUE;
					bRepeat = FALSE;
					tsErrChk( TS_PropertySetValString( testData->seqContextCVI, &errorInfo, "Parameters.DUT.SerialNumber", 0, g_szDut2SerialNumber ) );
					tsErrChk( TS_PropertySetValString( testData->seqContextCVI, &errorInfo, "Parameters.DUT.ProductCode", 0, g_szDut2ProductCode ) );
					tsErrChk( TS_PropertySetValNumber( testData->seqContextCVI, &errorInfo, "Parameters.DUT.TestSocketIndex", 0, 1 ) );
					SSU_GetFixtureClosedStatus( 2, &bLineStatus );

					if( bLineStatus == FALSE )
						WaitFixtureClosed( 2 );

					SSU_SwitchLed( 2, TRUE );
					SSU_EnablePa( 2, FALSE );
				}
				else
				{
					bRepeat = TRUE;
				}
			}
		
			if( bRepeat == TRUE )
				Delay( 1.0 );
		}
		while( bRepeat );

		if( g_bContinueTesting == FALSE && g_bBay1Scanned == FALSE && g_bBay2Scanned == FALSE )
		{
			error = TS_PropertySetValBoolean( testData->seqContextCVI, &errorInfo, "Parameters.ContinueTesting", 0, g_bContinueTesting );
		}
	}
	
Error:

	if( error != 0 )
	{
		testError->errorFlag = TRUE; 
		testError->errorCode = error;
		testData->replaceStringFuncPtr(&testError->errorMessage, errMsg);
		TS_PropertySetValBoolean( testData->seqContextCVI, &errorInfo, "Parameters.ContinueTesting", 0, FALSE );
	}
}

void __declspec(dllexport) TX_TEST TestCompleted( tTestData* testData, tTestError* testError )
{
	int error = 0;
	double dVoltage = 0;
	ERRORINFO errorInfo;
	ErrMsg errMsg 		= {'\0'};
	char* pszReport = 0;
	
	tsErrChk( TS_PropertyGetValString( testData->seqContextCVI, &errorInfo, 
								"RunState.ThisContext.ThisContext.RunState.Caller.RunState.Caller.Locals.Report",
								0, &pszReport ) );

	ErrChk( SWIFTDUTREADERLib_IDUTReaderTestCompleted( g_hDutReader, NULL, pszReport ) );

	if( g_bBay1Testing == TRUE )
	{
		SSU_EnablePa( 1, FALSE );
//		SSU_OpenFixture( 1 );
		
		SSU_SwitchLed( 1, FALSE );

		ErrChk( ValidateCalibration( 1 ) );

		g_bBay1Scanned = FALSE; 
		g_bBay1Testing = FALSE;
	}
	else if( g_bBay2Testing == TRUE )
	{
		SSU_EnablePa( 2, FALSE );
		SSU_OpenFixture( 2 );
		
		SSU_SwitchLed( 2, FALSE );

		ErrChk( ValidateCalibration( 2 ) );

		g_bBay2Scanned = FALSE; 
		g_bBay2Testing = FALSE;
	}

	SSU_FixtureCapBleadOff( FALSE );


	N6700_MeasureVoltage( g_hPSU1, &dVoltage , 1 );
	if( dVoltage > 1 )
		MessagePopup( "Warning", "Capacitor blead off not working in Bay 1, PSU1 32V" );
	N6700_MeasureVoltage( g_hPSU2, &dVoltage , 1 );
	if( dVoltage > 1 )
		MessagePopup( "Warning", "Capacitor blead off not working in Bay 1, PSU2 32V" );
	N6700_MeasureVoltage( g_hPSU3, &dVoltage , 1 );
	if( dVoltage > 1 )
		MessagePopup( "Warning", "Capacitor blead off not working in Bay 2, PSU3 32V" );
	N6700_MeasureVoltage( g_hPSU2, &dVoltage , 3 );
	if( dVoltage > 1 )
		MessagePopup( "Warning", "Capacitor blead off not working in Bay 2, PSU2 32V" );

Error:

	if( pszReport != 0 )
	{
		CA_FreeMemory( pszReport );
		pszReport = 0;
	}
	
	if( error != 0 )
	{
		testError->errorFlag = TRUE; 
		testError->errorCode = error;
		testData->replaceStringFuncPtr(&testError->errorMessage, errMsg);
		TS_PropertySetValBoolean( testData->seqContextCVI, &errorInfo, "Parameters.ContinueTesting", 0, FALSE );
	}

}

int WaitFixtureClosed( const int iDutPosition )
{
	int error = 0;          // required for tsErrChk
	BOOL bLineStatus = FALSE;

	int iStartButton = 0;
	int iGuiPanel = 0;
	int iExitLoop = 0;
	
	char szText[255] = {'\0'};

	iGuiPanel = NewPanel( 0, "", 550, 400, 66, 180 );
 
	iStartButton = NewCtrl( iGuiPanel, CTRL_SQUARE_COMMAND_BUTTON, "", 0, 0 );		
	SetCtrlAttribute( iGuiPanel, iStartButton, ATTR_WIDTH, 180 ); 
	SetCtrlAttribute( iGuiPanel, iStartButton, ATTR_HEIGHT, 66 );  
	sprintf( szText, "EMERGENCY START Bay %d", iDutPosition );
	SetCtrlAttribute( iGuiPanel, iStartButton, ATTR_LABEL_TEXT, szText ); 

	DisplayPanel( iGuiPanel );    

	InstallCtrlCallback( iGuiPanel, iStartButton, E_StartButton, 0); 

	do
	{  
		Delay(0.2);
		iExitLoop = GetUserEvent( 0, &iGuiPanel, &iStartButton ); 

		SSU_GetFixtureClosedStatus( iDutPosition, &bLineStatus );

		if( bLineStatus == TRUE )
			iExitLoop = 1;		
 	
	}
	while( !iExitLoop );

	DiscardPanel( 1 );
 
	return error;
}
	 

/*---------------------------------------------------------------------------*/
/*  										 E_StartButton
/*---------------------------------------------------------------------------*/
int CVICALLBACK E_StartButton (int panel, int control, int event,
                               void *callbackData, int eventData1,
                               int eventData2)
{
 
	if( event == EVENT_COMMIT )
	{
	}

	return(0);
}

